/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - geometry/mesh
// Copyright( c) 2015.  All Rights Reserved
//
// File:		AEStaticMesh.h
// Author:		Gianluca Belardelli
// Date:		05/05/2015
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AESTATICMESH_H_
#define _AESTATICMESH_H_

/// \brief La classe rappresenta una Mesh statica (di solito corrisponde ad un file .aemesh, ma &grave;
/// possibile anche crearla da codice).
/// Per creare istanze dello stesso oggetto &egrave; possibile utilizzare il metodo CreateInstance il
/// quale ritorna un oggetto di tipo AEStaticMeshInstance.
/// Per questioni di prestazioni e gestione della scena grafica, le Mesh statiche sono suddivise
/// in Submesh (AEStaticSubmesh), che vengono automaticamente istanziate nel momento stesso in cui
/// viene istanziata una AEStaticMesh.
class AEStaticSubmesh;
class AEStaticMeshInstance;
class AEMeshManager;

typedef AESmartPtr<AEStaticMesh> AEStaticMeshPtr;

class AEStaticMesh : public AEBaseMesh
{
// Members
protected:
	AEStaticSubmesh *m_lpSubmeshes;

// Methods
protected:
	AE_DLLIMPEXP void _init( void );
	AE_DLLIMPEXP virtual AEBOOL32 LoadFromFile( const char *lpFilename );

public:
	/** @name Costruttori e Distruttore */
	/// @{
	/// \brief Costruttore di default. Crea un oggetto AEStaticMesh vuoto.
	AE_DLLIMPEXP AEStaticMesh( void );
	
	/// \brief Costruttore della classe. Il costruttore non carica direttamente il file .aemesh passato
	/// come parametro. Per rendere effettivo il caricamento del file &egrave; necessario invocare il
	/// metodo EnsureLoaded(). Per caricare semplicemente un file .aemesh &egrave; consigliato utilizzare
	/// AEMeshManager::LoadStaticMeshFile.
	/// \param lpFileName Nome del file (inclusa l'estensione .aemesh) dal quale l'oggetto AEStaticMesh
	/// deve essere caricato.
	AE_DLLIMPEXP AEStaticMesh( const char *lpFileName );
	
	/// \brief Distruttore
	AE_DLLIMPEXP virtual ~AEStaticMesh( void );
	
	/// @}
	/** @name Allocazione/Deallocazione */
	/// @{
	/// \brief Alloca uno specifico numero di Submesh utilizzate da AEStaticMesh.
	/// Il metodo &egrave; da utilizzare solo se si vuole creare una Mesh statica
	/// da codice. Non &egrave; consigliato richiamare questo metodo per Mesh caricate
	/// da file .aemesh.
	/// \param nNumMeshes Numero di Submesh da allocare.
	AE_DLLIMPEXP virtual void AllocateSubmeshes( AEINT32 nNumMeshes );
	
	/// \brief Dealloca le Submesh presenti in questa Mesh.
	AE_DLLIMPEXP virtual void FreeSubmeshes( void );
	
	/// @}
	/** @name Accesso alle Submesh */
	/// @{
	/// \brief Ritorna la Submesh con l'indice specificato.
	/// \param nMeshIndex Indice della Submesh.
	/// \return Un oggetto di tipo AEBaseSubmesh contenente la Submesh specificata.
	AE_DLLIMPEXP virtual AEBaseSubmesh *GetBaseSubmesh( AEINT32 nMeshIndex ) const;
	
	/// \brief Ritorna la Submesh con l'indice specificato.
	/// \param nMeshIndex Indice della Submesh.
	/// \return Un oggetto di tipo AEStaticSubmesh contenente la Submesh specificata.
	AE_FORCEINLINE AEStaticSubmesh *GetSubmesh( AEINT32 nMeshIndex ) const;
	
	/// @}
	/** @name Creazione Instanza */
	/// @{
	/// \brief Crea un'istanza di questa Mesh.
	/// \param mTransform Matrice di trasformazione utilizzata per questa istanza.
	/// \return Un puntatore ad un oggetto AEStaticMeshInstance contenente l'istanza creata oppure
	/// AENULL in caso di errore.
	AE_FORCEINLINE AEStaticMeshInstance *CreateInstance( const AEMatrix4f &matTransform );
	
	/// \brief
	///   This override allows for providing an instance to fill out. If the passed pInstance is
	///   !=NULL then this is the return value
	AE_DLLIMPEXP AEStaticMeshInstance *CreateInstance( const AEMatrix4f& matTransform, AEStaticMeshInstance *lpInstance );
	
	/// \brief
	///   This override allows to specify whether the OnStaticMeshInstanceCreated method is triggered on the 
	///   currently installed physics module once the instance has been created. 
	AE_DLLIMPEXP AEStaticMeshInstance *CreateInstance( const AEMatrix4f& matTransform, AEStaticMeshInstance *lpInstance, AEBOOL32 bNotifyPhysics );
	
	/// @}
	/// @name Gestione delle risorse
	/// @{
	
	/// \brief Metodo chiamato internamente per aggiornare le statistiche sul consumo di memoria
	/// di questo oggetto.
	AE_DLLIMPEXP virtual void AccumulateMemoryFootprint( size_t &iUniqueSys, size_t &iUniqueGPU, size_t &iDependentSys, size_t &iDependentGPU );
	
	/// \brief Elimina i dati della mesh statica dalla memoria.
	AE_DLLIMPEXP AEBOOL32 Unload( void );
	
	/// \brief Ricarica la Mesh statica se originariamente era stata
	/// caricata da un file .aemesh.
	/// \return AETRUE se l'operazione ha avuto successo.
	AE_DLLIMPEXP AEBOOL32 Reload( void );
	
	/// \brief Carica una Mesh statica da file .aemesh.
	AE_DLLIMPEXP static AEStaticMesh *LoadStaticMesh( const char *lpFilename );
	
	/// \brief Ritorna il Resource Manager che gestisce questa Mesh.
	AE_DLLIMPEXP static AEMeshManager &GetResourceManager( void );
	
	/// \brief Ritorna AETRUE se la Mesh &egrave; stata caricata da file,
	/// altrimenti AEFALSE.
	AE_DLLIMPEXP AEBOOL32 IsLoadFromFile( void ) const;

	/// \brief Metodo statico che ritorna una Mesh che rappresenta una sfera.
	AE_DLLIMPEXP static AEStaticMesh *CreateSphereMesh( void );
	
	/// \brief Metodo statico che ritorna una Mesh che rappresenta un cubo.
	AE_DLLIMPEXP static AEStaticMesh *CreateCubeMesh( AEPrimitiveType ePrimType, AEFLOAT32 fCubeWidth );

	/// \brief Metodo statico che ritorna una Mesh che rappresenta un piano.
	AE_DLLIMPEXP static AEStaticMesh *CreatePlaneMesh( void );
};

#include "AEStaticMesh.inl"

#endif // _AESTATICMESH_H_
